"""
生成器的原理

函数的控制和暂停，堆内存

Python中函数的工作原理：
    1.python.exe会用一个叫做PyEval_EvalFromEx（c语言的函数）去执行具体的函数，然后会创建一个栈帧（stack_frame）。
    2.python一切皆对象，栈帧对象，字节码对象
    3.所有的栈帧都是分配在堆内存上，这就决定了栈帧可以独立于调用则存在
"""

import dis
import inspect

frame = None


def say():
    hello()


def hello():
    global frame
    frame = inspect.currentframe()


def use_dis():
    dis.dis(say)
    # 输出结果：
    """
     17       0 LOAD_GLOBAL              0 (hello)
              3 CALL_FUNCTION            0 (0 positional, 0 keyword pair)
              6 POP_TOP
              7 LOAD_CONST               0 (None)
             10 RETURN_VALUE
    """


def use_stack_frame():
    say()
    # 获取函数栈帧
    print(frame.f_code.co_name)
    caller_frame = frame.f_back
    print(caller_frame.f_code.co_name)
    # 输出结果：
    """
    hello
    say
    """


def gen_func():
    yield 1
    name = "kevin"
    yield 2
    age = 18
    return "success"


def use_gen_dis():
    gen = gen_func()
    dis.dis(gen)
    print(gen.gi_frame.f_lasti)
    print(gen.gi_frame.f_locals)
    next(gen)
    print(gen.gi_frame.f_lasti)
    print(gen.gi_frame.f_locals)
    # 输出结果：
    """
     51          0 LOAD_CONST               1 (1)
                 3 YIELD_VALUE
                 4 POP_TOP

     52          5 LOAD_CONST               2 ('kevin')
                 8 STORE_FAST               0 (name)
    
     53          11 LOAD_CONST               3 (2)
                 14 YIELD_VALUE
                 15 POP_TOP
    
     54          16 LOAD_CONST               4 (18)
                 19 STORE_FAST               1 (age)
    
     55          22 LOAD_CONST               5 ('success')
                 25 RETURN_VALUE
     -1
     {}
     3
     {}
    """


if __name__ == '__main__':
    use_dis()
    use_stack_frame()
    use_gen_dis()
